#include "main.h"
#include <math.h>

/**
 * @brief Initialize and start the cellular dialer connection process
 * This function executes the dialer startup script to establish cellular data connection
 * and captures the output for status verification and debugging purposes
 * @return uint8_t Returns TRUE if dialer started successfully, FALSE if any error occurred
 */
uint8_t wwwan_dialer_start(void)
{
    /* Buffer to store command execution output for analysis and logging */
    char buf[1024] = {0};
    
    /* Execute the dialer start command and capture output through pipe stream */
    FILE *fp = popen(DIALER_START, "r");

    /* Verify that command execution pipe was created successfully */
    if (fp != NULL)
    {
        /* Read the command output from the pipe into the buffer */
        if (fgets(buf, sizeof(buf) - 1, fp) != 0)
        {
            /* Display the dialer startup output for user information */
            printf("wwwan_dialer_start: %s\n", buf);
        }
    }
    else
    {
        /* Handle dialer startup failure with appropriate error message */
        printf("ERROR: wwwan_dialer_start error!\n");
        pclose(fp);
        return FALSE;
    }

    /* Close the command execution pipe to free system resources */
    pclose(fp);

    return TRUE;
}

/**
 * @brief Terminate the cellular dialer connection process
 * This function executes the dialer shutdown script to gracefully disconnect
 * cellular data connection and captures termination status for verification
 * @return uint8_t Returns TRUE if dialer stopped successfully, FALSE if any error occurred
 */
uint8_t wwwan_dialer_stop(void)
{
    /* Buffer to store command execution output for status verification */
    char buf[1024] = {0};
    
    /* Execute the dialer stop command and capture output through pipe stream */
    FILE *fp = popen(DIALER_STOP, "r");

    /* Verify that command execution pipe was created successfully */
    if (fp != NULL)
    {
        /* Read the command output from the pipe into the buffer */
        if (fgets(buf, sizeof(buf) - 1, fp) != 0)
        {
            /* Display the dialer shutdown output for user information */
            printf("wwwan_dialer_start: %s\n", buf);
        }
    }
    else
    {
        /* Handle dialer shutdown failure with appropriate error message */
        printf("ERROR: wwwan_dialer_start error!\n");
        pclose(fp);
        return FALSE;
    }

    /* Close the command execution pipe to free system resources */
    pclose(fp);
    return TRUE;
}

/**
 * @brief Extract alphanumeric characters from input string
 * This utility function filters and extracts only alphanumeric characters
 * from the input string, useful for cleaning AT command responses
 * @param in: Input string containing mixed characters including special symbols
 * @param out: Output buffer to store filtered alphanumeric characters only
 */
static void get_char_in_str(const char *in, char *out)
{
    /* Pointer to track current position in output buffer during character copying */
    char *p = out;
    
    /* Pointer to traverse input string while checking character validity */
    const char *next = in;

    /* Iterate through entire input string until null terminator is encountered */
    while ('\0' != *next)
    {
        /* Check if current character falls within alphanumeric ASCII range */
        if (*next >= '0' && *next <= 'z')
        {
            /* Update input pointer and copy valid character to output buffer */
            in = next;
            *p++ = *next;
        }
        
        /* Detect transition from alphanumeric to non-alphanumeric to break extraction */
        if (*in >= '0' && *in <= 'z' && (*next < '0' || *next > 'z'))
        {
            break;
        }
        next++;
    }

    /* Add null terminator to complete the output string properly */
    *p = '\0';
    
    /* Safety fallback to prevent empty string issues in caller functions */
    if (p == out)
        out = "NULL";
}

/**
 * @brief Send AT command to modem and retrieve response
 * This core function handles modem communication by sending AT commands
 * through serial interface and capturing the modem's response for processing
 * @param atcmd: AT command string to be sent to the modem device
 * @param respond: Buffer to store the modem's response after command execution
 * @return uint8_t Returns TRUE if command succeeded with OK response, FALSE on error
 */
static uint8_t get_atRespond(const char *atcmd, char *respond)
{
    /* Buffer to store raw serial data received from modem after command transmission */
    uint8_t uart_buffer[1024] = {0};
    
    /* Variable to track number of bytes received in current read operation */
    uint8_t rec_num = 0;
    
    /* Variable to accumulate total bytes received across multiple read operations */
    uint8_t rec_cnt = 0;

    /* Validate input parameters to prevent null pointer dereferencing */
    if ((atcmd == NULL) || (atcmd == NULL))
    {
        printf("get_atRespond: param is NULL!\n");
        return FALSE;
    }

    /* Send AT command to modem through serial interface and verify transmission */
    if (serial_send((uint8_t *)atcmd, strlen(atcmd)) > 0)
    {
        /* Allow sufficient time for modem to process command and generate response */
        delay_ms(300);

        /* Read response data from modem in multiple chunks if necessary */
        do
        {
            /* Accumulate total bytes received across multiple read operations */
            rec_cnt += rec_num;
            
            /* Read next chunk of data from serial buffer into reception buffer */
            rec_num = serial_recv(&uart_buffer[rec_cnt], APN_NAME_LEN);

        } while (rec_num);

        /* Check if modem responded with successful execution confirmation */
        if (strstr((char *)uart_buffer, "OK"))
        {
            /* Extract response content by skipping the echoed AT command prefix */
            sprintf(respond, "%s", uart_buffer + strlen(atcmd));
            
            /* Log the complete command and response for debugging and analysis */
            log_printf(MSG_INFO, "%s\n%s\n", atcmd, uart_buffer);
        }
        /* Handle modem error response indicating command failure */
        else if (strstr((char *)uart_buffer, "ERROR"))
        {
            printf("get_atRespond: return ERROR!\n");
            return FALSE;
        }
        /* Handle unexpected or malformed responses from modem */
        else
        {
            printf("get_atRespond: other ERROR!\n");
            return FALSE;
        }
    }
    else
    {
        return FALSE;
    }

    return TRUE;
}

/**
 * @brief Extract ICCID (Integrated Circuit Card Identifier) from modem response
 * ICCID is a unique 19-20 digit number identifying the SIM card in cellular networks
 * This function parses the modem response to extract the ICCID value for SIM identification
 * @param in: Input string containing raw modem response with ICCID information
 * @param out: Output buffer to store extracted ICCID value as string
 * @return uint8_t Returns TRUE indicating successful extraction (always succeeds in current implementation)
 */
static uint8_t get_CCID(const char *in, char *out)
{
    /* Use sscanf with pattern matching to extract ICCID from modem response format */
    sscanf(in, "%*s%s]", out);
    return TRUE;
}

/**
 * @brief Extract network operator information from COPS command response
 * This function parses the COPS (Current Operator Selection) command response
 * to identify the currently registered cellular network operator
 * @param in: Input string containing raw COPS command response from modem
 * @param out: Output buffer to store extracted operator name or identifier
 * @return uint8_t Returns SET if operator information extracted successfully, RESET on failure
 */
static uint8_t get_COPS(const char *in, char *out)
{
    /* Temporary buffer for intermediate string processing during extraction */
    char out_buffer[APN_NAME_LEN] = {0};
    
    /* State variable to track extraction success or failure status */
    uint8_t state = RESET;

    /* Use sscanf with quoted string pattern to extract operator name from response */
    if (sscanf(in, "%*[^\"]\"%[^\"]", out_buffer) < 0)
    {
        state = RESET;
    }
    else
    {
        /* Copy extracted operator information to output buffer */
        sprintf(out, "%s", out_buffer);
        state = SET;
    }

    return state;
}

/**
 * @brief Parse QENG (Engineering Mode) command response for detailed network information
 * This comprehensive function extracts cellular network parameters including signal metrics,
 * location area codes, cell identifiers, and network technology specifics from QENG response
 * @param in: Input string containing raw QENG command response with engineering data
 * @param out: Output buffer to store formatted network information string
 * @return uint8_t Returns TRUE if parsing successful, FALSE if response format invalid
 */
static uint8_t get_QENG(const char *in, char *out)
{
    /* Variables for numeric conversion of hexadecimal cell identifiers */
    long cellID = 0;
    long lac_tac = 0;
    
    /* Temporary buffer for network technology mode extraction */
    char mode_temp[16];

    /* Cellular network identification parameters */
    char mcc_temp[8] = {0};
    char mnc_temp[3] = {0};
    char lac_tac_temp[16] = {0};
    char cellID_temp[16] = {0};

    /* Radio signal quality and strength measurements */
    char rsrp_temp[5] = {0};
    char rsrq_temp[5] = {0};
    char rssi_temp[5] = {0};
    char sinr_temp[5] = {0};

    /* Locate the serving cell information section within the QENG response */
    char *servingcell_str = strstr(in, "servingcell");
    if (servingcell_str == NULL)
    {
        printf("servingcell_str null!");
        return FALSE;
    }

    /* Find the beginning of serving cell parameter list after initial identifier */
    char *servingcell = strstr(servingcell_str, ",");
    if (servingcell == NULL)
    {
        printf("servingcell null!");
        return FALSE;
    }

    /* Extract network connection state information from parameter list */
    char *state = strstr(servingcell + 1, ",");
    if (state == NULL)
    {
        printf("state null!");
        return FALSE;
    }

    /* Locate network technology mode specification within quoted section */
    char *mode = strstr(state + 2, "\"");
    if (mode == NULL)
    {
        printf("mode null!");
        return FALSE;
    }

    /* Extract the network technology mode string (GSM, LTE, WCDMA, etc.) */
    if ((mode - state) > 1)
    {
        memset(mode_temp, 0x00, sizeof(mode_temp));
        memcpy(mode_temp, state + 2, mode - state - 2);
        // printf("mode:%s\n", mode_temp);
    }

    /* Parse response based on specific network technology type detected */
    /* Different network technologies have different response formats and parameters */
    if ((strstr(mode_temp, "GSM") != 0) || (strstr(mode_temp, "WCDMA") != 0) || (strstr(mode_temp, "CDMA") != 0) ||
        (strstr(mode_temp, "HDR") != 0))
    {
        /* Process 2G/3G network technologies (GSM, WCDMA, CDMA, HDR) */
        /* These technologies share similar response format with MCC, MNC, LAC, CellID parameters */

        // printf("mode1:%s\n", mode_temp);

        /* Token counter for tracking parameter position during parsing */
        int i = 0;
        
        /* String tokenization pointer for parameter extraction */
        char *result = NULL;

        /* Begin tokenizing the parameter list using comma as delimiter */
        result = strtok(state, ",");

        /* Iterate through all parameters in the comma-separated list */
        while (result != NULL)
        {
            /* Extract specific parameters based on their position in the list */
            switch (i)
            {
            case 1:
                /* Extract Mobile Country Code (MCC) for network identification */
                memset(mcc_temp, 0x00, sizeof(mcc_temp));
                memcpy(mcc_temp, result, sizeof(mcc_temp));
                // printf("mcc_temp = %s\n", mcc_temp);
                break;
            case 2:
                /* Extract Mobile Network Code (MNC) for operator identification */
                memset(mnc_temp, 0x00, sizeof(mnc_temp));
                memcpy(mnc_temp, result, sizeof(mnc_temp));
                // printf("mnc_temp = %s\n", mnc_temp);
                break;
            case 3:
                /* Extract Location Area Code (LAC) for geographic area identification */
                memset(lac_tac_temp, 0x00, sizeof(lac_tac_temp));
                memcpy(lac_tac_temp, result, sizeof(lac_tac_temp));
                // printf("lac_temp = %s\n", lac_tac_temp);
                break;
            case 4:
                /* Extract Cell ID for specific base station identification */
                memset(cellID_temp, 0x00, sizeof(cellID_temp));
                memcpy(cellID_temp, result, sizeof(cellID_temp));
                // printf("sinr_temp = %s\n", sinr_temp);
                break;
            default:
                break;
            }
            i++;
            result = strtok(NULL, ",");
        }
    }
    else if (strstr(mode_temp, "LTE") != 0)
    {
        /* Process 4G LTE network technology with enhanced signal parameters */
        /* LTE provides additional signal quality metrics like RSRP, RSRQ, SINR */

        // printf("mode2:%s\n", mode_temp);

        /* Token counter for tracking parameter position during parsing */
        int i = 0;
        
        /* String tokenization pointer for parameter extraction */
        char *result = NULL;

        /* Begin tokenizing the parameter list using comma as delimiter */
        result = strtok(state, ",");
        
        /* Iterate through all parameters in the comma-separated list */
        while (result != NULL)
        {
            /* Extract LTE-specific parameters based on their position in the list */
            switch (i)
            {
            case 2:
                /* Extract Mobile Country Code (MCC) for LTE network */
                memset(mcc_temp, 0x00, sizeof(mcc_temp));
                strcpy(mcc_temp, result);
                // printf("mcc_temp = %s\n", mcc_temp);
                break;

            case 3:
                /* Extract Mobile Network Code (MNC) for LTE operator */
                memset(mnc_temp, 0x00, sizeof(mnc_temp));
                strcpy(mnc_temp, result);
                // printf("mnc_temp = %s\n", mnc_temp);
                break;

            case 4:
                /* Extract Cell ID for LTE base station identification */
                memset(cellID_temp, 0x00, sizeof(cellID_temp));
                strcpy(cellID_temp, result);
                // printf("cellID_temp = %s\n", cellID_temp);
                break;

            case 10:
                /* Extract Tracking Area Code (TAC) for LTE location area */
                memset(lac_tac_temp, 0x00, sizeof(lac_tac_temp));
                strcpy(lac_tac_temp, result);
                // printf("lac_tac_temp = %s\n", lac_tac_temp);
                break;

            case 11:
                /* Extract Reference Signal Received Power for LTE signal strength */
                memset(rsrp_temp, 0x00, sizeof(rsrp_temp));
                strcpy(rsrp_temp, result);
                // printf("rsrp_temp = %s\n", rsrp_temp);
                break;

            case 12:
                /* Extract Reference Signal Received Quality for LTE signal quality */
                memset(rsrq_temp, 0x00, sizeof(rsrq_temp));
                strcpy(rsrq_temp, result);
                // printf("rsrq_temp = %s\n", rsrq_temp);
                break;

            case 13:
                /* Extract Received Signal Strength Indicator for overall signal power */
                memset(rssi_temp, 0x00, sizeof(rssi_temp));
                strcpy(rssi_temp, result);
                // printf("rssi_temp = %s\n", rssi_temp);
                break;

            case 14:
                /* Extract Signal to Interference plus Noise Ratio for signal clarity */
                memset(sinr_temp, 0x00, sizeof(sinr_temp));
                strcpy(sinr_temp, result);
                // printf("sinr_temp = %s\n", sinr_temp);
                break;

            default:
                break;
            }
            i++;
            result = strtok(NULL, ",");
        }
    }
    else if (strstr(mode_temp, "TDSCDMA") != 0)
    {
        /* Process TD-SCDMA network technology (China-specific 3G standard) */
        /* TD-SCDMA has unique parameter ordering and signal measurement types */

        // printf("mode3:%s\n", mode_temp);

        /* Token counter for tracking parameter position during parsing */
        int i = 0;
        
        /* String tokenization pointer for parameter extraction */
        char *result = NULL;

        /* Begin tokenizing the parameter list using comma as delimiter */
        result = strtok(state, ",");

        /* Iterate through all parameters in the comma-separated list */
        while (result != NULL)
        {
            /* Extract TD-SCDMA specific parameters based on position */
            switch (i)
            {
            case 1:
                /* Extract Mobile Country Code for TD-SCDMA network */
                memset(mcc_temp, 0x00, sizeof(mcc_temp));
                strcpy(mcc_temp, result);
                // printf("mcc_temp = %s\n", mcc_temp);
                break;
            case 2:
                /* Extract Mobile Network Code for TD-SCDMA operator */
                memset(mnc_temp, 0x00, sizeof(mnc_temp));
                strcpy(mnc_temp, result);
                // printf("mnc_temp = %s\n", mnc_temp);
                break;
            case 3:
                /* Extract Location Area Code for TD-SCDMA geographic area */
                memset(lac_tac_temp, 0x00, sizeof(lac_tac_temp));
                strcpy(lac_tac_temp, result);
                // printf("lac_tac_temp = %s\n", lac_tac_temp);
                break;
            case 4:
                /* Extract Cell ID for TD-SCDMA base station */
                memset(cellID_temp, 0x00, sizeof(cellID_temp));
                strcpy(cellID_temp, result);
                // printf("cellID_temp = %s\n", cellID_temp);
                break;
            case 6:
                /* Extract RSSI for TD-SCDMA signal strength measurement */
                memset(rssi_temp, 0x00, sizeof(rssi_temp));
                strcpy(rssi_temp, result);
                // printf("rssi_temp = %s\n", rssi_temp);
            default:
                break;
            }
            i++;
            result = strtok(NULL, ",");
        }
    }

    /* Convert hexadecimal location and cell identifiers to decimal format */
    lac_tac = hex_to_int(lac_tac_temp);
    cellID = hex_to_int(cellID_temp);

    /* Format all extracted network information into comprehensive output string */
    sprintf(out,
            "Network mode: %s\nCurrent RSRP: %d dBm\nCurrent RSRQ: %d dB\nCurrent RSSI: %d dBm\nCurrent SINR: %d "
            "dB\nCurrent MCC: %d\nCurrent MNC: %d\nCurrent LAC/TAC: %ld\nCurrent CellID: %ld\n",
            mode_temp, atoi(rsrp_temp), atoi(rsrq_temp), atoi(rssi_temp), atoi(sinr_temp), atoi(mcc_temp),
            atoi(mnc_temp), lac_tac, cellID);

    return TRUE;
}

/**
 * @brief Parse HCSQ command response for signal quality information
 * This function extracts signal measurement data from HCSQ command response
 * which provides simplified signal quality information compared to QENG
 * @param in: Input string containing raw HCSQ command response from modem
 * @param out: Output buffer to store formatted signal quality information
 * @return uint8_t Returns TRUE if parsing successful, FALSE if response format invalid
 */
static uint8_t get_HCSQ(const char *in, char *out)
{
    /* Temporary buffers for storing individual signal parameter values */
    char network_temp[APN_NAME_LEN] = {0};
    char rsrp_temp[APN_NAME_LEN] = {0};
    char rsrq_temp[APN_NAME_LEN] = {0};
    char rssi_temp[APN_NAME_LEN] = {0};
    char sinr_temp[APN_NAME_LEN] = {0};

    /* Initialize all temporary buffers to ensure clean string operations */
    memset(&network_temp, 0x00, sizeof(network_temp));
    memset(&rsrp_temp, 0x00, sizeof(rsrp_temp));
    memset(&rsrq_temp, 0x00, sizeof(rsrq_temp));
    memset(&rssi_temp, 0x00, sizeof(rssi_temp));
    memset(&sinr_temp, 0x00, sizeof(sinr_temp));

    /* Process LTE network signal information from HCSQ response */
    if (strstr(in, "LTE"))
    {
        /* Use sscanf with precise pattern matching to extract LTE signal parameters */
        sscanf(in, "%*[^: ]: %*[^\"]\"%[^\"]\",%[^,],%[^,],%[^,],%[^\r]", network_temp, rssi_temp, rsrq_temp, rsrp_temp,
               sinr_temp);
        
        /* Format extracted signal parameters into human-readable output string */
        sprintf(
            out,
            "Network mode: %s\nCurrent RSRP: %s dBm\nCurrent RSRQ: %s dB\nCurrent RSSI: %s dBm\nCurrent SINR: %s dB\n",
            network_temp, rsrp_temp, rsrq_temp, rssi_temp, sinr_temp);
    }
    /* Handle various network service states and technology types */
    else if (strstr(in, "NOSERVICE"))
        strcpy(out, "NOSERVICE");
    else if (strstr(in, "CDMA"))
        strcpy(out, "CDMA");
    else if (strstr(in, "HDR"))
        strcpy(out, "HDR");
    else if (strstr(in, "GSM"))
        strcpy(out, "GSM");
    else if (strstr(in, "WCDMA"))
        strcpy(out, "WCDMA");
    else
        return FALSE;

    return TRUE;
}

/**
 * @brief Check if specific network interface exists and is available
 * This function queries system network interfaces to verify if the specified
 * PPP interface is present and configured in the system
 * @param net_none: Network interface name to check for existence (e.g., "ppp0", "ppp1")
 * @return int Returns 0 if interface exists, -1 if interface not found or error occurred
 */
static uint8_t check_net_none_up(char *net_none)
{
    /* Socket file descriptor for network interface query operations */
    int fd = 0;
    
    /* Buffer to store network interface information structures */
    struct ifreq ifr_buf[10]; /* Maximum query for 10 network interfaces */
    
    /* Interface configuration structure for system interface query */
    struct ifconf ifc = {0};
    
    /* Variable to store actual number of network interfaces found */
    int if_num = 0;
    
    /* Return value for system call error checking */
    int ret = 0;

    /* Create socket descriptor for network interface configuration queries */
    fd = socket(AF_INET, SOCK_DGRAM, 0);

    /* Verify socket creation succeeded before proceeding with interface query */
    if (fd <= 0)
    {
        return -1;
    }

    /* Configure interface query parameters with buffer size and location */
    ifc.ifc_len = sizeof(ifr_buf);
    ifc.ifc_buf = (caddr_t)ifr_buf;
    
    /* Execute system call to retrieve network interface configuration */
    ret = ioctl(fd, SIOCGIFCONF, (char *)&ifc);
    if (ret)
    {
        close(fd);
        return -1;
    }
    
    /* Calculate actual number of network interfaces from returned data size */
    if_num = ifc.ifc_len / sizeof(struct ifreq); /* Actual number of network interfaces */
    
    /* Iterate through all discovered network interfaces to find target interface */
    while (if_num--)
    {
        /* Compare interface names to find matching target interface */
        if ((strcmp(ifr_buf[if_num].ifr_name, net_none)) == 0)
        {
            close(fd);
            return 0;
        }
    }
    
    /* Close socket descriptor and return not found status */
    close(fd);
    return -1;
}

/**
 * @brief Retrieve comprehensive modem information for specified network interface
 * This master function orchestrates the complete modem information retrieval process
 * including device identification, SIM status, network registration, and signal metrics
 * @param dev: Network device name specifying which modem interface to query ("ppp0" or "ppp1")
 * @return uint8_t Returns TRUE if all modem information retrieved successfully, FALSE on any error
 */
static uint8_t get_modemMsg(char *dev)
{
    /* Pointer to store UART port configuration based on device specification */
    char *uart_port = NULL;
    
    /* Buffer for storing raw AT command responses from modem */
    char at_respond[APN_NAME_LEN * 10] = {0};
    
    /* Temporary buffer for modem model type extraction and processing */
    char model_type_temp[APN_NAME_LEN] = {0};
    
    /* Buffer for processed and cleaned AT command output */
    char at_show[APN_NAME_LEN] = {0};
    
    /* Formatted output strings for different modem information categories */
    char dev_name[APN_NAME_LEN * 2] = {0};
    char model_type[APN_NAME_LEN * 2] = {0};
    char model_firmware[APN_NAME_LEN * 2] = {0};
    char ICCID[APN_NAME_LEN * 2] = {0};
    char IMSI[APN_NAME_LEN * 2] = {0};
    char IMEI[APN_NAME_LEN * 2] = {0};
    char Carrier[APN_NAME_LEN * 2] = {0};
    char SSI[APN_NAME_LEN * 2] = {0};

/* Conditional compilation branch for high-level modem information API */
#if 1
    /* Return status variable for function success/failure tracking */
    uint8_t ret = TRUE;
    
    /* Structures to store cellular module hardware information */
    CellularModuleInfo moduleInfo[2];
    
    /* Structures to store cellular network connection information */
    CellularNetworkInfo networkInfo[2];

    /* Select appropriate information structure based on device specification */
    CellularNetworkInfo *pNetWorkInfo = strcmp(dev, "ppp0") == 0 ? &networkInfo[0] : &networkInfo[1];
    CellularModuleInfo *pModuleInfo = strcmp(dev, "ppp0") == 0 ? &moduleInfo[0] : &moduleInfo[1];
    
    /* High-level API workflow for modem information retrieval */
    // 1. Read wireless module hardware information
    // 2. Read wireless module network connection information
    
    /* Initialize information structures to ensure clean data processing */
    memset(moduleInfo, 0x00, sizeof(moduleInfo));
    memset(networkInfo, 0x00, sizeof(networkInfo));
    
    /* Execute high-level API calls to retrieve cellular information */
    if (!get_cellularModuleInfo(moduleInfo) || !get_cellularNetworkInfo(networkInfo))
    {
        /* Set error status and continue with default values if API calls fail */
        strcpy(pNetWorkInfo->simStatus, "ERROR");
        ret = FALSE;
    }

    /* Format all retrieved information into human-readable output strings */
    sprintf(dev_name, "dev name: %s\n", dev);
    sprintf(model_type, "model type: %s\n", pModuleInfo->moduleName);
    sprintf(model_firmware, "model firmware version: %s\n", pModuleInfo->firmwareVersion);
    sprintf(ICCID, "sim status: %s\nIntegrate circuit card identity (ICCID): %s\n", pNetWorkInfo->simStatus,
            pNetWorkInfo->iccid);
    sprintf(IMSI, "International Mobile Subscriber Identity (IMSI): %s\n", pNetWorkInfo->imsi);
    sprintf(IMEI, "International Mobile Equipment Identity (IMEI): %s\n", pModuleInfo->imei);
    sprintf(Carrier, "Carrier Information: %s\n", pNetWorkInfo->mno);
    sprintf(SSI,
            "Network mode: %s\nCurrent RSRP: %s\nCurrent RSRQ: %s\nCurrent RSSI: %s\nCurrent SINR: %s\nCurrent MCC: "
            "\nCurrent MNC: \nCurrent LAC/TAC: \nCurrent CellID: \n",
            pNetWorkInfo->mode, pNetWorkInfo->rsrp, pNetWorkInfo->rsrq, pNetWorkInfo->rssi, pNetWorkInfo->sinr);
    
    /* Display all formatted modem information to the user */
    printf("%s%s%s%s%s%s%s%s", dev_name, model_type, model_firmware, ICCID, IMSI, IMEI, Carrier, SSI);

    return ret;
#else
#endif

    /* Legacy low-level AT command implementation for modem information retrieval */
    /* This branch uses direct serial communication and AT command parsing */

    /* Check if specified network interface exists and is available */
    if (check_net_none_up(dev) != 0)
    {
        /* Generate error output when requested network interface is not available */
        sprintf(dev_name, "dev name: %s\n", dev);
        sprintf(model_type, "model type: \n");
        sprintf(model_firmware, "model firmware version: \n");
        sprintf(ICCID, "sim status: ERROR\nIntegrate circuit card identity (ICCID): \n");
        sprintf(IMSI, "International Mobile Subscriber Identity (IMSI): \n");
        sprintf(IMEI, "International Mobile Equipment Identity (IMEI): \n");
        sprintf(Carrier, "Carrier Information: \n");
        sprintf(SSI, "Network mode: \nCurrent RSRP: \nCurrent RSRQ: \nCurrent RSSI: \nCurrent SINR: \nCurrent MCC: "
                     "\nCurrent MNC: \nCurrent LAC/TAC: \nCurrent CellID: \n");
        printf("%s%s%s%s%s%s%s%s", dev_name, model_type, model_firmware, ICCID, IMSI, IMEI, Carrier, SSI);
        return FALSE;
    }

    /* Determine UART port configuration based on specified network device */
    if (!strcmp(dev, "ppp0"))
    {
        uart_port = PORT_PPP0;
    }
    else if (!strcmp(dev, "ppp1"))
    {
        uart_port = PORT_PPP1;
    }
    else
    {
        return FALSE;
    }

    /* Format device name output string for display */
    sprintf(dev_name, "dev name: %s\n", dev);

    /* Initialize UART communication with modem device */
    if (!uart_init(uart_port, 115200, 8, 'N', 1))
    {
        printf("ERROR: uart_init error!\n");
        return FALSE;
    }

    /* Send ATE command to enable modem echo for command verification */
    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (!get_atRespond("ATE\r", at_respond))
    {
        printf("ERROR: ATE setting error!\n");
        return FALSE;
    }

    /* Retrieve modem model information using CGMM command */
    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+CGMM\r", at_respond))
    {
        /* Parse model information from standard response format */
        if (strstr(at_respond, "+CGMM:"))
        {
            sscanf(at_respond, "%*[^: ]: %[^\n]", at_show);
        }
        else
        {
            /* Fallback parsing for non-standard response formats */
            get_char_in_str(at_respond, at_show);
        }

        sprintf(model_type, "model type: %s\n", at_show);
    }
    else
    {
        sprintf(model_type, "model type: \n");
    }
    strcpy(model_type_temp, at_show);

    /* Retrieve modem firmware version using CGMR command */
    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+CGMR\r", at_respond))
    {
        /* Parse firmware version from standard response format */
        if (strstr(at_respond, "+CGMR:"))
        {
            sscanf(at_respond, "%*[^: ]: %[^\n]", at_show);
        }
        else
        {
            /* Fallback parsing for non-standard response formats */
            get_char_in_str(at_respond, at_show);
        }

        sprintf(model_firmware, "model firmware version: %s\n", at_show);
    }
    else
    {
        sprintf(model_firmware, "model firmware version: \n");
    }

/* Conditional compilation for ICCID retrieval */
#if 1
    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+ICCID\r", at_respond))
    {
        get_CCID(at_respond, at_show);
        sprintf(ICCID, "sim status: OK\nIntegrate circuit card identity (ICCID): %s\n", at_show);
    }
    else
    {
        sprintf(ICCID, "sim status: ERROR\nIntegrate circuit card identity (ICCID): \n");
    }
#endif

    // sprintf(ICCID, "sim status: OK\nIntegrate circuit card identity (ICCID): 123456789\n");

    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+CIMI\r", at_respond))
    {
        get_char_in_str(at_respond, at_show);
        sprintf(IMSI, "International Mobile Subscriber Identity (IMSI): %s\n", at_show);
    }
    else
    {
        sprintf(IMSI, "International Mobile Subscriber Identity (IMSI): \n");
    }

    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+CGSN\r", at_respond))
    {
        sscanf(at_respond, "%*[^\"]\"%[^\"]", at_show);

        if (strlen(at_show) == 0)
        {
            memset(at_show, 0x00, APN_NAME_LEN);
            get_char_in_str(at_respond, at_show);
        }

        sprintf(IMEI, "International Mobile Equipment Identity (IMEI): %s\n", at_show);
    }
    else
    {
        sprintf(IMEI, "International Mobile Equipment Identity (IMEI): \n");
    }

    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (get_atRespond("AT+COPS?\r", at_respond))
    {
        if (get_COPS(at_respond, at_show))
        {
            sprintf(Carrier, "Carrier Information: %s\n", at_show);
        }
        else
        {
            sprintf(Carrier, "Carrier Information: \n");
        }
    }

    memset(at_show, 0x00, APN_NAME_LEN);
    memset(at_respond, 0x00, APN_NAME_LEN);
    if (strstr(model_type_temp, "EC20") || strstr(model_type_temp, "EC600S"))
    {
        if (get_atRespond("AT+QENG=\"servingcell\"\r", at_respond))
        {
            if (get_QENG(at_respond, at_show))
                sprintf(SSI, "%s\n", at_show);
            else
                sprintf(SSI, "Network mode: \nCurrent RSRP: \nCurrent RSRQ: \nCurrent RSSI: \nCurrent SINR: \nCurrent "
                             "MCC: \nCurrent MNC: \nCurrent LAC/TAC: \nCurrent CellID: \n");
        }
        else
        {
            sprintf(SSI, "Network mode: \nCurrent RSRP: \nCurrent RSRQ: \nCurrent RSSI: \nCurrent SINR: \nCurrent MCC: "
                         "\nCurrent MNC: \nCurrent LAC/TAC: \nCurrent CellID: \n");
        }
    }
    else if (strstr(model_type_temp, "SLM"))
    {
        if (get_atRespond("AT^HCSQ?\r", at_respond))
        {
            if (get_HCSQ(at_respond, at_show))
            {
                sprintf(SSI, "%s\n", at_show);
            }
            else
                sprintf(SSI, "Network mode: \nCurrent RSRP: \nCurrent RSRQ: \nCurrent RSSI: \nCurrent SINR: \n");
        }
        else
        {
            sprintf(SSI, "Network mode: \nCurrent RSRP: \nCurrent RSRQ: \nCurrent RSSI: \nCurrent SINR: \n");
        }
    }

    printf("%s%s%s%s%s%s%s%s", dev_name, model_type, model_firmware, ICCID, IMSI, IMEI, Carrier, SSI);

    if (!uart_destory())
    {
        printf("uart_destory error!\n");
        return FALSE;
    }

    return TRUE;

}

/**
 * @brief wwan_modem_showMsg
 *
 * @param dev
 * @return uint8_t
 */
uint8_t wwan_modem_showMsg(char *dev)
{
    if (!strcmp(dev, "ppp0"))
    {
        if (!get_modemMsg("ppp0"))
        {
            return FALSE;
        }
    }
    else if (!strcmp(dev, "ppp1"))
    {
        if (!get_modemMsg("ppp1"))
        {
            return FALSE;
        }
    }
    else if (!strcmp(dev, "all"))
    {
        if (!get_modemMsg("ppp0") || !get_modemMsg("ppp1"))
        {
            return FALSE;
        }
    }
    else
    {
        return FALSE;
    }

    return TRUE;
}